#include "jeu.h"
#include<stdlib.h>
#include<stdio.h>
#include<cassert>


const int nbvie=2;

int valeurabsolue(int n)
{
	if (n>=0)
		return n;
	else
		return -n;
}

int signe(int n)
{
	if (n>0)
		return 1;
	else if (n<0)
		return -1;
	else
		return 0;

}
void initJeu(Jeu* j,const int map[HAUTEUR][LARGEUR])
{
	j->t=creerTer(map);
    j->br=creerBar(j->t);
	j->bl=creerBal(j->br);
	j->vie=nbvie;
	j->valeurFin=0;
}

void libereJeu(Jeu* j)
{
	libereBal(j->bl);
	libereBar(j->br);
	libereTer(j->t);
	free(j);
}

Jeu* creerJeu(const int map[HAUTEUR][LARGEUR])
{
    Jeu* j;
    j=(Jeu*)malloc(sizeof(Jeu));
      if(j == NULL)
    	{
      		printf("allocation impossible \n");
       		exit(EXIT_FAILURE);
    	}
    initJeu(j,map);
    return j;
}



Terrain* getTerrainJeu(Jeu* j)
{
	return j->t;
}

Balle* getBalleJeu(Jeu* j)
{
	return j->bl;
}

Barre* getBarreJeu(Jeu* j)
{
	return j->br;
}

int getVieJeu(Jeu* j)
{
	return j->vie;
}


void setVieJeu(Jeu* j)
{
	j->vie--;
}

void gagneVieJeu(Jeu* j)
{
	j->vie++;
}

int getFinJeu(Jeu* j)
{
	return j->valeurFin;
}

void setFinJeu(Jeu* j, int n)
{
	j->valeurFin=n;
}

const Terrain* getConstTerrainJeu(const Jeu* j)
{
	return j->t;
}

const Balle* getConstBalleJeu(const Jeu* j)
{
	return j->bl;
}

const Barre* getConstBarreJeu(const Jeu* j)
{
	return j->br;
}

const int getConstVieJeu(const Jeu* j)
{
	return j->vie;
}

void actionClavierJeu(Jeu* j, const char touche)
{
	switch(touche)
	{
		case 'g' :
				deplaceGaucheBar(j->t, j->br);
				break;
		case 'd' :
				deplaceDroiteBar(j->t, j->br);
				break;
	}
}


void actionSourisJeu(Jeu* j, int xs)
{
    if (positionValideBar(j->t,xs+4))
    (j->br->positionX) = xs;
}


void rattrapeOptionJeu(Jeu* j)
{
    int i;
    int f;
    int haut;
    int valeur;

    Terrain* ter = getTerrainJeu(j);
    TableauOp* to = getOptionTerrain(ter);
    f = getFinTableau(to);

    for(i=0 ; i<f ; i++)
    {
		assert ( i < to->fin );
        assert (to->tab[i] != 0);

        haut=getPositionYOption( getIemeOptionTableau( to, i) );
        assert ( haut <= getDimyTer( getTerrainJeu( j ) ) - 1 );

		if( haut < getDimyTer( getTerrainJeu( j ) ) -1 )/*si l'option est dans le terrain*/
        {}

        else /*si l'option est à hauteur de la barre*/
        {
            if (    (getPositionXOption(getIemeOptionTableau(to,i)) < getGaucheBar(j->br)) ||
                    (getPositionXOption(getIemeOptionTableau(to,i)) > getDroiteBar(j->br))    )
                    /*si l'option n' est pas toucher par la barre*/
            {}
            else
            {
               valeur = getNumeroOption(getIemeOptionTableau(to,i));

                switch(valeur)
                {

                case 1:
                    //reduitBar(j->br);
                    gagneVieJeu(j);
                    setEtatNormalBal(j->bl);
                    break;

                case 2:
                    //augmenteBar(j->br)
                    setVieJeu(j);
					setEtatNormalBal(j->bl);
                    break;

                case 3:
                  setEtatAcierBal(j->bl);
                //case 4:


                default:
                break;

				}

            }
            supprimerElementTableau(to,i);/*l'option n'est plus en jeu*/
			f = getFinTableau(to);/*pour la boucle for*/
			i=i-1;/*pour la boucle for*/
        }
    }
}



void calculerNouvelleDirectionJeu(Jeu* j)
{
    assert(j->bl->etat != 0);
    Balle* bal = j->bl;
    Barre* bar = j->br;
    Terrain* ter = j->t;
	int dx = getDirXBal(bal);
	int dy = getDirYBal(bal);
	int px = getPositionXBal(bal);
	int py = getPositionYBal(bal);
	int x = signe(dx);
	int y = 0;

	while(valeurabsolue(x)/*1 ou 0*/ <= valeurabsolue(dx)/*0,1 ou 2*/)
	{
		if(valeurabsolue(y)/*1 ou 0*/ > valeurabsolue(dy)/*0 ou 1*/)
		{
			y = dy;
		}

		while(valeurabsolue(y)<=valeurabsolue(dy))//la boucle: (1,0);(1,1);(2,1)
		{
			if( positionValideTer(ter, px+ x, py + y) == 0)/*cas où il ne se passe rien*/
			{}
			if (positionValideTer(ter, px + x, py + y) >= 2)/*mur(2) ou brique(3)*/
			{
				if (getEtatBal(bal) == 1)//normal
				{

				if( ( positionValideTer( ter, px + x, py) >= 2 ) &&
					( positionValideTer( ter, px, py + y) >= 2 ) )/*test coins superieurs terrain*/
						setDirBal(bal, (-dx), (-dy));
				else if (positionValideTer(ter, px + x, py) >= 2 )/*test horizontal, brique et mur*/
					setDirBal(bal, (-dx), dy);
				else if (positionValideTer (ter, px, py + y) >= 2)/*test vertical, brique et plafond*/
					setDirBal(bal, dx, (-dy));
				else
					setDirBal(bal, (-dx), (-dy));/*test brique touché par un angle*/
				}

				else if ( getEtatBal(bal) == 2 )//acier
				{

				if( (positionValideTer(ter, px + x, py) == 2 ) &&
						(positionValideTer(ter, px, py + y) ) == 2 )/*test coins supérieurs terrain*/
						setDirBal(bal, (-dx), (-dy));
				else if (positionValideTer(ter, px + x,py) == 2)/*test mur*/
					setDirBal(bal, (-dx), dy);
				else if (positionValideTer (ter, px, py + y) == 2)/*test mur gauche*/
					setDirBal(bal, dx, (-dy));
				//else
					//setDirBal(j->bl, (-dx), (-dy));
				}

			}
		if (positionValideTer(ter, px + x, py + y) ==3)
			{
				Brique* brq = getBriqueTer(ter, px + x, py + y);
				if (getEtatBal(bal) == 1)//normal
				{
					setResistanceBrique(brq);
				}
				else if (getEtatBal(bal) == 2)//acier
				{
					setResistanceZeroBrique(brq);
				}
			enclencheOptionTer(ter, brq);

			}
		else if(positionValideTer(ter, px + x,py + y) == 1)/*rattrape ou tombe*/
			{
				if ( (px + x < getGaucheBar(bar) ) || (px + x>getDroiteBar(bar)) )
				{
					//la balle balle tombe, on perd une vie
				}
				else
				{
					rattrappeBal(bal, bar, px + x);
				}
			}
		y=y+signe(dy);
		}
	x=x+signe(dx);
	if(x==0)
	{x=1;}
	}
}


